package com.gjy.core;

import com.gjy.Level;
import com.gjy.Logger;
import com.gjy.use.ES;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * PUT /logger
 * {
 *   "mappings": {
 *     "properties": {
 *       "datetime": {
 *         "type": "date"
 *       },
 *       "thread": {
 *         "type": "text",
 *         "fields" : {
 *             "keyword" : {
 *               "type" : "keyword",
 *               "ignore_above" : 256
 *             }
 *           }
 *       },
 *       "level": {
 *         "type": "keyword"
 *       },
 *       "classname": {
 *         "type": "text",
 *         "fields" : {
 *             "keyword" : {
 *               "type" : "keyword",
 *               "ignore_above" : 256
 *             }
 *           }
 *       },
 *       "methodname": {
 *         "type": "text",
 *         "fields" : {
 *             "keyword" : {
 *               "type" : "keyword",
 *               "ignore_above" : 256
 *             }
 *           }
 *       },
 *       "message": {
 *         "type": "text",
 *         "fields" : {
 *             "keyword" : {
 *               "type" : "keyword",
 *               "ignore_above" : 256
 *             }
 *           }
 *       },
 *       "throwable": {
 *         "type": "text",
 *         "fields" : {
 *             "keyword" : {
 *               "type" : "keyword",
 *               "ignore_above" : 256
 *             }
 *           }
 *       }
 *     }
 *   }
 * }
 * @author 宫静雨
 * @version 1.0
 */
public class ESLogger implements Logger {
    private Class<?> clazz;
    private static final ES ES = new ES();
    private static final String INDEX = "logger";

    public ESLogger(Class<?> clazz) {
        this.clazz = clazz;
    }

    private void insert(String message, Level level, Throwable... t) {
        RestHighLevelClient client = ES.client();
        IndexRequest request = new IndexRequest().index(INDEX);
        Map<String,Object> map = new HashMap<>();
        map.put("datetime", LocalDateTime.now());
        map.put("thread", Thread.currentThread().getName());
        map.put("level", level);
        map.put("classname", clazz.getName());
        map.put("methodname", Thread.currentThread().getStackTrace()[3].getMethodName());
        map.put("message", message);
        if (t.length > 0) {
            map.put("throwable", t[0].getMessage());
        }
        request.source(map,XContentType.JSON);
        try {
            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void info(String message) {
        insert(message, Level.INFO);
    }

    @Override
    public void info(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.INFO);
    }

    @Override
    public void info(String message, Throwable t) {
        insert(message, Level.INFO, t);
    }

    @Override
    public void debug(String message) {
        insert(message, Level.DEBUG);
    }

    @Override
    public void debug(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.DEBUG);
    }

    @Override
    public void debug(String message, Throwable t) {
        insert(message, Level.DEBUG, t);
    }

    @Override
    public void warn(String message) {
        insert(message, Level.WARN);
    }

    @Override
    public void warn(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.WARN);
    }

    @Override
    public void warn(String message, Throwable t) {
        insert(message, Level.WARN, t);
    }

    @Override
    public void error(String message) {
        insert(message, Level.ERROR);
    }

    @Override
    public void error(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.ERROR);
    }

    @Override
    public void error(String message, Throwable t) {
        insert(message, Level.ERROR, t);
    }
}
